﻿using Mozhi.Abp.Core.Extensions;
using Mozhi.Abp.Domain.BasicData;
using System;
using Volo.Abp;

namespace mozhi.smarterp.Business
{
    public class DocumentEntity : EntityBase
    {
        public virtual Guid ProductId { get; protected set; }

        public virtual Product Product { get; protected set; }

        /// <summary>
        /// 辅助单位
        /// </summary>
        public virtual Guid AuxiliaryUnitId {  get; protected set; }

        public virtual Unit AuxiliaryUnit {  get; protected set; }

        /// <summary>
        /// 辅助数量
        /// </summary>
        public virtual decimal AuxiliaryQuantity {  get; protected set; }

        public virtual ProductAuxiliaryUnit ProductAuxiliaryUnit { get; protected set; }

        /// <summary>
        /// 辅助单位和计价单位换算率
        /// </summary>
        public virtual decimal ConversionRate {  get; protected set; }

        /// <summary>
        /// 计价单位
        /// </summary>
        public virtual Guid BasicUnitId { get; protected set; }

        /// <summary>
        /// 计价单位数量
        /// </summary>
        public virtual decimal BasicQuantity { get; protected set; }

        /// <summary>
        /// 计价单位单价
        /// </summary>
        public virtual decimal Price { get; protected set; }

        /// <summary>
        /// 计价单位含税单价
        /// </summary>
        public virtual decimal PriceIncludeTax { get; protected set; }

        /// <summary>
        /// 计价单位不含税单价
        /// </summary>
        public virtual decimal PriceExcludeTax { get; protected set; }

        public virtual Guid? TaxRateId { get; protected set; }

        public virtual TaxRate TaxRate { get; protected set; }

        public virtual decimal? TaxRateValue { get; protected set; }

        public virtual decimal? DiscountRate { get; protected set; }

        public virtual decimal? TaxAmountFr { get; protected set; }

        public virtual decimal? TaxAmount { get; protected set; }

        public virtual decimal AmountFr { get; protected set; }

        public virtual decimal Amount { get; protected set; }

        public virtual decimal TotalAmountFr { get; protected set; }

        public virtual decimal TotalAmount { get; protected set; }

        public virtual string Remark { get; protected set; }

        public virtual void ChangeIndex(int index)
        {
            Index = index;
        }

        protected DocumentEntity() { }

        public DocumentEntity(Guid id , Product product,  decimal price, TaxRate taxRate,  string remark)
        {

            Product = product;
            TaxRate = taxRate;

            Id = id;

            ProductId = Product == null ? default : product.Id;

            BasicUnitId = Product == null ? default : product.BasicUnitId;

            TaxRateId = TaxRate == null ? null : TaxRate.Id;
            TaxRateValue = TaxRate == null ? null : TaxRate.Rate;

            Price = price;
            Remark = remark;
        }

        public DocumentEntity(Guid id, Product product, Unit auxiliaryUnit , ProductAuxiliaryUnit productAuxiliaryUnit , decimal auxiliaryQuantity, decimal price, TaxRate taxRate, string remark)
        {

            Id = id;
            Change(product, auxiliaryUnit, productAuxiliaryUnit, auxiliaryQuantity, price, taxRate, remark);
        }

        public virtual void Change(Product product, Unit auxiliaryUnit, ProductAuxiliaryUnit productAuxiliaryUnit, decimal auxiliaryQuantity, decimal price, TaxRate taxRate, string remark)
        {
            Product = product;
            TaxRate = taxRate;
            AuxiliaryUnit = auxiliaryUnit;
            ProductAuxiliaryUnit = productAuxiliaryUnit;
            AuxiliaryQuantity = auxiliaryQuantity;

            ProductId = Product == null ? default : product.Id;
            BasicUnitId = Product == null ? default : product.BasicUnitId;
            AuxiliaryUnitId = AuxiliaryUnit == null ? default : AuxiliaryUnit.Id;
            AuxiliaryQuantity = auxiliaryQuantity;
            ConversionRate = ProductAuxiliaryUnit == null ? 0 : ProductAuxiliaryUnit.ConversionRate;

            TaxRateId = TaxRate == null ? null : TaxRate.Id;
            TaxRateValue = TaxRate == null ? null : TaxRate.Rate;

            Price = price;
            Remark = remark;
        }

        public virtual void CalculateBaiscUnitQuantity()
        {
            if (AuxiliaryUnitId == Product.BasicUnitId)
            {
                BasicQuantity = AuxiliaryQuantity;
                return;
            }

            if (ConversionRate <= 0)
                throw new UserFriendlyException("单位换算率必须大于0", "100000");

            BasicQuantity = AuxiliaryQuantity * ConversionRate;
        }


        public virtual void CalculateAmount(bool includeTax, decimal exchangeRate , bool isGift = false)
        {
            if (isGift)
            {
                Price = 0;
                PriceExcludeTax = 0;
                PriceIncludeTax = 0;
                Amount = 0;
                AmountFr = 0;
                TaxAmount = 0;
                TaxAmountFr = 0;
                TotalAmount = 0;
                TotalAmountFr = 0;
                TaxRateId = null;
                TaxRateValue = null;

                return;
            }

            if (Price <= 0)
                throw new UserFriendlyException("单价必须大于0", "100000");

            if (AuxiliaryQuantity <= 0)
                throw new UserFriendlyException("数量必须大于0", "100000");

            if (TaxRateId.HasValue && TaxRateValue < 0)
                throw new UserFriendlyException("税率必须大于等于0", "100000");

            if (includeTax == true && (!TaxRateId.HasValue || !TaxRateValue.HasValue))
                throw new UserFriendlyException("单据含税必须包含税率", "100000");

            PriceIncludeTax = TaxRate.GetIncludeTaxValue(Price, includeTax);
            PriceExcludeTax = TaxRate.GetExcludeTaxValue(Price, includeTax);

            AmountFr = (PriceExcludeTax * BasicQuantity).ToMoney();
            Amount = (AmountFr * exchangeRate).ToMoney();

            TotalAmountFr = (PriceIncludeTax * BasicQuantity).ToMoney();
            TotalAmount = (TotalAmountFr * exchangeRate).ToMoney();

            TaxAmountFr = TotalAmountFr - AmountFr;

            TaxAmount = TotalAmount - Amount;
        }

        #region
        protected virtual void Validate()
        {
            Check.NotDefaultOrNull<Guid>(ProductId, nameof(ProductId));

            if (Product == null)
                throw new UserFriendlyException("产品不存在", "100000");

            Product.Validate();

            if (Price <= 0)
                throw new UserFriendlyException("单价必须大于0", "100000");

            if (TaxRate != null)
                TaxRate.Validate();

            if (AuxiliaryUnit == null)
                throw new UserFriendlyException($"产品：{Product.Code}-{Product.Name}的单位不存在", "100000");

            AuxiliaryUnit.Validate();

            if (BasicUnitId != AuxiliaryUnitId && ProductAuxiliaryUnit == null)
                throw new UserFriendlyException($"产品：{Product.Code}-{Product.Name}的单位和计价单位换算关系不存在", "100000");

            Check.NotDefaultOrNull<Guid>(BasicUnitId, nameof(BasicUnitId));
        }
        #endregion
    }
}
